aboutsummaryrefslogtreecommitdiff
path: root/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-01-24 13:09:50 +0000
committerFuwn <[email protected]>2026-01-24 13:09:50 +0000
commit396acf3bbbe00a192cb0ea0a9ccf91b1d8d2850b (patch)
treeb9df4ca6a70db45cfffbae6fdd7252e20fb8e93c /src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx
downloadumami-main.tar.xz
umami-main.zip
Initial commitHEADmain
Created from https://vercel.com/new
Diffstat (limited to 'src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx')
-rw-r--r--src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx b/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx
new file mode 100644
index 0000000..56c6f43
--- /dev/null
+++ b/src/app/(main)/websites/[websiteId]/settings/WebsiteShareForm.tsx
@@ -0,0 +1,93 @@
+import {
+ Button,
+ Column,
+ Form,
+ FormButtons,
+ FormSubmitButton,
+ IconLabel,
+ Label,
+ Row,
+ Switch,
+ TextField,
+} from '@umami/react-zen';
+import { RefreshCcw } from 'lucide-react';
+import { useState } from 'react';
+import { useConfig, useMessages, useUpdateQuery } from '@/components/hooks';
+import { getRandomChars } from '@/lib/generate';
+
+const generateId = () => getRandomChars(16);
+
+export interface WebsiteShareFormProps {
+ websiteId: string;
+ shareId?: string;
+ onSave?: () => void;
+ onClose?: () => void;
+}
+
+export function WebsiteShareForm({ websiteId, shareId, onSave, onClose }: WebsiteShareFormProps) {
+ const { formatMessage, labels, messages, getErrorMessage } = useMessages();
+ const [currentId, setCurrentId] = useState(shareId);
+ const { mutateAsync, error, touch, toast } = useUpdateQuery(`/websites/${websiteId}`);
+ const { cloudMode } = useConfig();
+
+ const getUrl = (shareId: string) => {
+ if (cloudMode) {
+ return `${process.env.cloudUrl}/share/${shareId}`;
+ }
+
+ return `${window?.location.origin}${process.env.basePath || ''}/share/${shareId}`;
+ };
+
+ const url = getUrl(currentId);
+
+ const handleGenerate = () => {
+ setCurrentId(generateId());
+ };
+
+ const handleSwitch = () => {
+ setCurrentId(currentId ? null : generateId());
+ };
+
+ const handleSave = async () => {
+ const data = {
+ shareId: currentId,
+ };
+ await mutateAsync(data, {
+ onSuccess: async () => {
+ toast(formatMessage(messages.saved));
+ touch(`website:${websiteId}`);
+ onSave?.();
+ onClose?.();
+ },
+ });
+ };
+
+ return (
+ <Form onSubmit={handleSave} error={getErrorMessage(error)} values={{ url }}>
+ <Column gap>
+ <Switch isSelected={!!currentId} onChange={handleSwitch}>
+ {formatMessage(labels.enableShareUrl)}
+ </Switch>
+ {currentId && (
+ <Row alignItems="flex-end" gap>
+ <Column flexGrow={1}>
+ <Label>{formatMessage(labels.shareUrl)}</Label>
+ <TextField value={url} isReadOnly allowCopy />
+ </Column>
+ <Column>
+ <Button onPress={handleGenerate}>
+ <IconLabel icon={<RefreshCcw />} label={formatMessage(labels.regenerate)} />
+ </Button>
+ </Column>
+ </Row>
+ )}
+ <FormButtons justifyContent="flex-end">
+ <Row alignItems="center" gap>
+ {onClose && <Button onPress={onClose}>{formatMessage(labels.cancel)}</Button>}
+ <FormSubmitButton isDisabled={false}>{formatMessage(labels.save)}</FormSubmitButton>
+ </Row>
+ </FormButtons>
+ </Column>
+ </Form>
+ );
+}